/*
 * Copyright (C) 2010-2012 Geometer Plus <contact@geometerplus.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301, USA.
 */

package cn.dns.reader.network;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashSet;
import java.util.Set;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.net.Uri;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.RemoteException;
import android.text.TextUtils;
import android.widget.RemoteViews;
import android.widget.Toast;
import cn.dns.zlibrary.core.network.ZLNetworkException;
import cn.dns.zlibrary.core.network.ZLNetworkManager;
import cn.dns.zlibrary.core.network.ZLNetworkRequest;

import com.hctforgreen.greenservice.R;
import com.hctforgreen.greenservice.model.BookListEntity.BookEntity;
import com.mato.sdk.proxy.Address;

/**
 * 版本更新
 * 
 * @author denghb
 * 
 */
public class UpdateVersionService extends Service {

	public static final String SHOW_NOTIFICATIONS_KEY = "org.geometerplus.android.fbreader.network.ShowNotifications";

	public static final String TITLE_KEY = "org.geometerplus.android.fbreader.network.Title";
	public static final String BOOK_FORMAT_KEY = "org.geometerplus.android.fbreader.network.BookFormat";
	private Address address;

	private String title;

	public interface Notifications {
		int DOWNLOADING_STARTED = 0x0001;
		int ALREADY_DOWNLOADING = 0x0002;

		int ALL = 0x0003;
	}

	private String downloadingUrl;
	// private Set<BookEntity> mDownloadingUrls = Collections
	// .synchronizedSet(new HashSet<BookEntity>());

	/**
	 * 等待下载队列
	 */
	// private List<BookEntity> mWaitingUrls = Collections
	// .synchronizedList(new ArrayList<BookEntity>());

	private Set<Integer> myOngoingNotifications = new HashSet<Integer>();

	// private volatile int myServiceCounter;

	// private void doStart() {
	// ++myServiceCounter;
	// }
	//
	// private void doStop() {
	// if (--myServiceCounter == 0) {
	// stopSelf();
	// }
	// }

	@Override
	public IBinder onBind(Intent intent) {
		return new BookDownloaderInterface.Stub() {
			public boolean isBeingDownloaded(String url) {
				if (contains(url)) {
					return true;
				} else {
					return false;
				}

			}

			@Override
			public boolean hasDownloadingUrl() throws RemoteException {
				if (downloadingUrl != null
						&& downloadingUrl.trim().length() > 0) {
					return true;
				}
				return false;
			}

			@Override
			public boolean cancelDownloadingUrl(String url)
					throws RemoteException {
				// if (url != null && url.equals(downloadingUrl)) {
				// downloadingUrl = null;
				// return true;
				// }
				return false;
			}
		};
	}

	@Override
	public void onDestroy() {
		final NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
		for (int notificationId : myOngoingNotifications) {
			notificationManager.cancel(notificationId);
			clearDownloadingURLs(notificationManager, notificationId);
		}
		myOngoingNotifications.clear();

		super.onDestroy();
	}

	/**
	 * 在下载Service销毁时，如果还有没有下载完成的，设置为下载失败状态
	 * 
	 * @param notificationId
	 */
	private void clearDownloadingURLs(NotificationManager notificationManager,
			int notificationId) {

		if (downloadingUrl == null || downloadingUrl.trim().length() == 0) {
			return;
		}

		notificationManager.notify(
				notificationId,
				createDownloadFinishNotification(getApplicationContext()
						.getString(R.string.update_hint), 0, notificationId));
	}

	@Override
	public void onStart(Intent intent, int startId) {
		super.onStart(intent, startId);

		if (intent == null) {
			return;
		}
		final Uri uri = intent.getData();
		if (uri == null) {
			return;
		}
		intent.setData(null);

		final String url = uri.toString();

		String fileName = BookEntity.makeBookFileName(url, "apk",
				getApplicationContext());
		if (fileName == null) {
			return;
		}

		int index = fileName.lastIndexOf(File.separator);
		if (index != -1) {
			final String dir = fileName.substring(0, index);
			final File dirFile = new File(dir);
			if (!dirFile.exists() && !dirFile.mkdirs()) {

				Toast.makeText(
						getApplicationContext(),
						getString(R.string.cannot_create_directory).replace(
								"%s", dirFile.getPath()), Toast.LENGTH_SHORT)
						.show();
				return;
			}
			if (!dirFile.exists() || !dirFile.isDirectory()) {
				Toast.makeText(
						getApplicationContext(),
						getString(R.string.cannot_create_directory).replace(
								"%s", dirFile.getPath()), Toast.LENGTH_SHORT)
						.show();
				return;
			}
		}

		final File fileFile = new File(fileName);
		if (fileFile.exists()) {
			if (!fileFile.isFile()) {

				Toast.makeText(
						getApplicationContext(),
						getString(R.string.cannot_create_file).replace("%s",
								fileFile.getPath()), Toast.LENGTH_SHORT).show();
				return;
			}

			// doStop();
			/**
			 * TODO:点击已经存在文件的下载链接会去调用阅读器的功能
			 */
			// startActivity(getStartEntryCatalogIntent(bookEntity));
			// return;
		}
		String title = intent.getStringExtra(TITLE_KEY);
		String address = intent.getStringExtra("address.host");
		int port = intent.getIntExtra("address.port", 8123);
		if (!TextUtils.isEmpty(address)) {
			try {
				this.address = new Address(address, port);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		if (title == null || title.length() == 0) {
			title = fileFile.getName();
		}

		// Util.tryToDeleteBookZip(bookEntity, getApplicationContext());

		if (title == null || title.trim().length() == 0) {// 下载掌上通apk文件
			startFileDownload(url, "", fileFile, getApplicationContext()
					.getString(R.string.app_name));
		} else {
			startFileDownload(url, "", fileFile, title);
		}

	}

	private Notification createDownloadCancelNotification(File file,
			String title) {
		final String tickerText = getApplicationContext().getString(
				R.string.download_cancel_hint);
		final String contentText = getApplicationContext().getString(
				R.string.download_cancel_hint);
//		final Notification notification = new Notification(
//				android.R.drawable.stat_sys_download_done, tickerText,
//				System.currentTimeMillis());
//		notification.flags |= Notification.FLAG_AUTO_CANCEL;

		final Intent intent = new Intent();
		final PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
				intent, 0);
//		notification.setLatestEventInfo(getApplicationContext(), title,
//				contentText, contentIntent);
		//20161201 390697 兼容6.0
		Notification.Builder notificationBuilder = new Notification.Builder(getApplicationContext());
		Notification notification = notificationBuilder.setContentTitle(title)
				.setContentText(contentText)
				.setContentIntent(contentIntent)
				.setSmallIcon(android.R.drawable.stat_sys_download_done)
				.build();
		notification.flags |= Notification.FLAG_AUTO_CANCEL;
		return notification;
	}

	/**
	 * 
	 * @param title
	 * @param what
	 *            0:失败,1:成功,2:解析失败
	 * @return
	 */
	private Notification createDownloadFinishNotification(String title,
			int what, final int notificationId) {
		final String tickerText = getTickerText(what);
		final String contentText = getContentText(what);
//		final Notification notification = new Notification(
//				android.R.drawable.stat_sys_download_done, tickerText,
//				System.currentTimeMillis());
//		notification.flags |= Notification.FLAG_AUTO_CANCEL;

		// final Intent intent = (what == 1)?
		// getStartEntryCatalogIntent(bookEntity):new Intent();
		final Intent intent = new Intent();
		final PendingIntent contentIntent = PendingIntent.getActivity(this,
				notificationId, intent, PendingIntent.FLAG_CANCEL_CURRENT);
//		notification.setLatestEventInfo(getApplicationContext(), title,
//				contentText, contentIntent);
		//20161201 390697 兼容6.0
		Notification.Builder notificationBuilder = new Notification.Builder(getApplicationContext());
		Notification notification = notificationBuilder.setContentTitle(title)
				.setContentText(contentText)
				.setContentIntent(contentIntent)
				.setSmallIcon(android.R.drawable.stat_sys_download_done)
				.build();
		notification.flags |= Notification.FLAG_AUTO_CANCEL;
		return notification;
	}

	private String getContentText(int what) {
		String contentText = "";
		if (what == 0) {
			contentText = getString(R.string.content_error);
		} else if (what == 1) {
			contentText = getString(R.string.content_success);
		} else if (what == 2) {
			contentText = getString(R.string.book_zip_txt_error_hint);
		}
		return contentText;
	}

	private String getTickerText(int what) {
		String tickerText = "";
		if (what == 0) {
			tickerText = getString(R.string.ticker_error);
		} else if (what == 1) {
			tickerText = getString(R.string.ticker_success);
		} else if (what == 2) {
			tickerText = getString(R.string.book_zip_txt_error_hint);
		}

		return tickerText;
	}

	private Notification createDownloadProgressNotification(String title) {
		final RemoteViews contentView = new RemoteViews(getPackageName(),
				R.layout.download_notification);
		contentView.setTextViewText(R.id.download_notification_title, title);
		contentView.setTextViewText(R.id.download_notification_progress_text,
				"");
		contentView.setProgressBar(R.id.download_notification_progress_bar,
				100, 0, true);

		final PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
				new Intent(), 0);

		final Notification notification = new Notification();
		notification.icon = android.R.drawable.stat_sys_download;
		notification.flags |= Notification.FLAG_ONGOING_EVENT;
		notification.contentView = contentView;
		notification.contentIntent = contentIntent;

		return notification;
	}

	private void startFileDownload(final String downloadUrl,
			final String sslCertificate, final File file, final String title) {
		this.downloadingUrl = downloadUrl;
		final int notificationId = NetworkNotifications.Instance()
				.getBookDownloadingId();
		final Notification progressNotification = createDownloadProgressNotification(title);

		final NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
		myOngoingNotifications.add(Integer.valueOf(notificationId));
		notificationManager.notify(notificationId, progressNotification);

		final Handler progressHandler = new Handler() {
			public void handleMessage(Message message) {
				final int progress = message.what;
				final RemoteViews contentView = (RemoteViews) progressNotification.contentView;

				if (progress < 0) {
					contentView.setTextViewText(
							R.id.download_notification_progress_text, "");
					contentView.setProgressBar(
							R.id.download_notification_progress_bar, 100, 0,
							true);
				} else {
					contentView.setTextViewText(
							R.id.download_notification_progress_text, ""
									+ progress + "%");
					contentView.setProgressBar(
							R.id.download_notification_progress_bar, 100,
							progress, false);
				}
				final NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
				notificationManager
						.notify(notificationId, progressNotification);
			}

		};

		final Handler downloadFinishHandler = new Handler() {
			public void handleMessage(Message message) {
				final NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
				notificationManager.cancel(notificationId);
				myOngoingNotifications.remove(Integer.valueOf(notificationId));
				// notificationManager.notify(
				// notificationId,
				// createDownloadFinishNotification(title, message.what,
				// notificationId));

				Intent intent = new Intent(Intent.ACTION_VIEW);
				intent.setDataAndType(
						Uri.parse("file://"
								+ BookEntity.makeBookFileName(downloadingUrl,
										"apk", getApplicationContext())),
						"application/vnd.android.package-archive");
				intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
				startActivity(intent);
			}
		};

		final Handler downloadCancelHandler = new Handler() {
			public void handleMessage(Message message) {

				// if (bookEntity.doWhatClick
				// .equals(HctConstants.ON_ACTIVITY_KEY_DO_UPDATE_CLICK)) {
				// updateBookProgress(bookEntity, 100);
				// updateBookZipState(
				// bookEntity,
				// HctConstants.ON_ACTIVITY_KEY_BOOK_ZIP_STATE_ANALISIS_DONE);
				// sendDownloadedProgressBroadcast(bookEntity.download_url,
				// true, 100);
				// } else {
				// updateBookProgress(bookEntity, 0);
				// updateBookZipState(
				// bookEntity,
				// HctConstants.ON_ACTIVITY_KEY_BOOK_ZIP_STATE_ALREADY_CANCEL);
				// sendDownloadedProgressBroadcast(bookEntity.download_url,
				// true, 0);
				// }
				final NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
				notificationManager.cancel(notificationId);
				myOngoingNotifications.remove(Integer.valueOf(notificationId));
				notificationManager.notify(notificationId,
						createDownloadCancelNotification(file, title));
			}
		};
		final ZLNetworkRequest request = new ZLNetworkRequest(downloadUrl,
				sslCertificate, null) {
			public void handleStream(InputStream inputStream, int length)
					throws IOException, ZLNetworkException {
				/**
				 * 刷新间隔
				 */
				final int updateIntervalMillis = 2000;

				int downloadedPart = 0;
				long progressTime = System.currentTimeMillis()
						+ updateIntervalMillis;
				if (length <= 0) {
					progressHandler.sendEmptyMessage(-1);
				}
				OutputStream outStream;
				try {
					outStream = new FileOutputStream(file);
				} catch (FileNotFoundException ex) {
					throw new ZLNetworkException(
							ZLNetworkException.ERROR_CREATE_FILE,
							file.getPath());
				}
				try {
					final byte[] buffer = new byte[8192];
					while (!isCancel(downloadUrl)) {
						final int size = inputStream.read(buffer);

						if (size <= 0) {
							break;
						}
						downloadedPart += size;

						if (length > 0) {
							final long currentTime = System.currentTimeMillis();
							if (currentTime > progressTime) {
								progressTime = currentTime
										+ updateIntervalMillis;

								float fPart = Float.valueOf(downloadedPart)
										* 100f / Float.valueOf(length);
								progressHandler.sendEmptyMessage((int) fPart);

							}
							/*
							 * if (downloadedPart * 100 / length > 95) { throw
							 * new IOException("debug exception"); }
							 */
						}
						outStream.write(buffer, 0, size);
						/*
						 * try { Thread.currentThread().sleep(200); } catch
						 * (InterruptedException ex) { }
						 */
					}

					if (isCancel(downloadUrl)) {
						downloadFinishHandler.sendEmptyMessage(0);
					}
				} finally {

					inputStream.close();
					outStream.close();
				}
			}
		};

		final Thread downloader = new Thread(new Runnable() {
			public void run() {
				boolean success = false;
				try {
					ZLNetworkManager.Instance().perform(request, address);
					success = true;
				} catch (ZLNetworkException e) {
					e.printStackTrace();
					file.delete();
				} finally {
					// if (!downloadingUrlsContains(downloadUrl)) {
					// return;
					// }
					// if (success) {
					// analisisIngHandler.sendEmptyMessage(success ? 1 : 0);
					// } else if (!success) {
					if (success) {
						downloadFinishHandler.sendEmptyMessage(0);
					} else {
						downloadCancelHandler.sendEmptyMessage(0);
					}
					// }

				}
			}
		});
		downloader.setPriority(Thread.MIN_PRIORITY);
		downloader.start();
	}

	private boolean contains(String url) {
		if (downloadingUrl != null && downloadingUrl.equals(url)) {
			return true;
		} else {
			return false;
		}
	}

	private boolean isCancel(String url) {
		return false;
	}

}
